﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DatabaseManager.Utilities;
using SqlSugar;

namespace DatabaseManager.WinForms.Services
{
    /// <summary>
    /// 模型生成服务，基于数据库连接动态生成实体类
    /// </summary>
    public class ModelGenerationService
    {
        private readonly DbConnectionService _dbConnectionService;
        private readonly string _defaultOutputDir; // 默认输出目录（可配置）

        /// <summary>
        /// 初始化模型生成服务
        /// </summary>
        /// <param name="dbConnectionService">数据库连接服务</param>
        public ModelGenerationService(DbConnectionService dbConnectionService)
        {
            _dbConnectionService = dbConnectionService ??
                throw new ArgumentNullException(nameof(dbConnectionService));

            // 默认输出目录（可改为从配置文件读取）
            _defaultOutputDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "GeneratedModels");
        }

        /// <summary>
        /// 生成数据库实体类（使用默认目录和命名空间）
        /// </summary>
        /// <returns>生成结果（成功/失败信息）</returns>
        public GenerationResult GenerateModels()
        {
            // 默认命名空间（建议与项目结构匹配）
            string defaultNamespace = "DatabaseManager.WinForms.Models";
            return GenerateModels(_defaultOutputDir, defaultNamespace);
        }

        /// <summary>
        /// 生成数据库实体类（自定义目录和命名空间）
        /// </summary>
        /// <param name="outputDir">实体类输出目录</param>
        /// <param name="namespace">实体类命名空间</param>
        /// <returns>生成结果（成功/失败信息）</returns>
        public GenerationResult GenerateModels(string outputDir, string @namespace)
        {
            try
            {
                // 1. 检查数据库连接状态
                if (!_dbConnectionService.Connect())
                {
                    var connError = _dbConnectionService.GetLastException()?.Message ?? "数据库连接失败";
                    return GenerationResult.Failure($"无法生成实体类：{connError}");
                }

                // 2. 获取数据库连接客户端
                ISqlSugarClient db = _dbConnectionService.GetDbClient();

                // 3. 确保输出目录存在
                if (!Directory.Exists(outputDir))
                {
                    Directory.CreateDirectory(outputDir);
                }

                //4.生成实体类（基于DbFirst）
                db.DbFirst
                    .IsCreateAttribute() // 生成数据注解（如[Key]、[Column]）
                    .StringNullable()   // 字符串类型设为可空
                    .FormatFileName(t => StringHelper.ToCamelCase(t)) // 文件名：驼峰式（如user_info.cs → userInfo.cs）
                    .FormatClassName(t => StringHelper.ToPascalCase(t)) // 类名：帕斯卡式（如user_info → UserInfo）
                    .FormatPropertyName(t => StringHelper.ToCamelCase(t)) // 属性名：驼峰式（如user_id → userId）
                    .CreateClassFile(outputDir, @namespace); // 生成文件

                //// 4. 生成实体类（基于DbFirst，适配C#7.3）
                //db.DbFirst
                //    .IsCreateAttribute() // 生成数据注解
                //    .StringNullable()   // 字符串类型设为可空（数据库层面）
                //    .DisableNullableReferenceType() // 关键：禁用C#8.0的可为null引用类型语法
                //    .FormatFileName(t => StringHelper.ToCamelCase(t))
                //    .FormatClassName(t => StringHelper.ToPascalCase(t))
                //    .FormatPropertyName(t => StringHelper.ToCamelCase(t))
                //    .CreateClassFile(outputDir, @namespace); // 生成文件

                return GenerationResult.Success(
                    $"实体类生成成功！\r\n输出目录：{outputDir}\r\n命名空间：{@namespace}");
            }
            catch (Exception ex)
            {
                // 捕获生成过程中的异常（如权限不足、表结构错误）
                string errorMsg = ex.InnerException != null ? ex.InnerException.Message : ex.Message;
                return GenerationResult.Failure($"生成失败：{errorMsg}");
            }
        }


        /// <summary>
        /// 生成数据库实体类（支持进度报告）
        /// </summary>
        /// <param name="outputDir">输出目录</param>
        /// <param name="namespace">命名空间</param>
        /// <param name="progress">进度回调（0-100）</param>
        /// <returns>生成结果</returns>
        public GenerationResult GenerateModels(string outputDir, string @namespace, IProgress<int> progress = null)
        {
            try
            {
                // 1. 检查连接（报告10%进度）
                progress?.Report(10);
                if (!_dbConnectionService.Connect())
                {
                    var connError = _dbConnectionService.GetLastException()?.Message ?? "数据库连接失败";
                    return GenerationResult.Failure($"无法生成实体类：{connError}");
                }

                // 2. 获取数据库客户端（报告20%进度）
                progress?.Report(20);
                ISqlSugarClient db = _dbConnectionService.GetDbClient();

                // 3. 获取所有表（用于计算进度）
                progress?.Report(30);
                List<string> tableNames = GetTableNames(db); // 调用自定义方法获取表名
                if (tableNames == null || tableNames.Count == 0)
                {
                    return GenerationResult.Failure("未在数据库中找到任何表");
                }


                // 4. 确保目录存在（报告40%进度）
                progress?.Report(40);
                if (!Directory.Exists(outputDir))
                {
                    Directory.CreateDirectory(outputDir);
                }

                // 5. 逐个生成表实体（按表数量计算进度）
                int totalTables = tableNames.Count;
                int processedTables = 0;

                foreach (var tableName in tableNames)
                {
                    // 生成单个表的实体类
                    db.DbFirst
                        .IsCreateAttribute()
                        .StringNullable()                        
                        .Where(tableName) // 直接传入表名字符串（低版本SqlSugar支持的语法）
                                          // 或使用lambda表达式：.Where(t => t == tableName)
                        .FormatFileName(t => StringHelper.ToCamelCase(t))
                        .FormatClassName(t => StringHelper.ToPascalCase(t))
                        .FormatPropertyName(t => StringHelper.ToCamelCase(t))
                        .CreateClassFile(outputDir, @namespace);

                    // 更新进度（40% + 60% * 已处理比例）
                    processedTables++;
                    int currentProgress = 40 + (int)((processedTables * 1.0 / totalTables) * 60);
                    progress?.Report(currentProgress);
                }

                // 6. 完成（100%进度）
                progress?.Report(100);
                return GenerationResult.Success(
                    $"实体类生成成功！\r\n输出目录：{outputDir}\r\n命名空间：{@namespace}\r\n共生成 {totalTables} 个表");
            }
            catch (Exception ex)
            {
                string errorMsg = ex.InnerException != null ? ex.InnerException.Message : ex.Message;
                return GenerationResult.Failure($"生成失败：{errorMsg}");
            }
        }


        /// <summary>
        /// 适配低版本 SqlSugar，通过 SQL 查询获取数据库表名
        /// </summary>
        /// <param name="db">SqlSugar 客户端</param>
        /// <returns>表名列表</returns>
        private List<string> GetTableNames(ISqlSugarClient db)
        {
            // 根据数据库类型执行不同的 SQL（此处以 MySQL 为例）
            if (db.CurrentConnectionConfig.DbType == SqlSugar.DbType.MySqlConnector)
            {
                // 从连接字符串中提取当前数据库名（关键！替代 DATABASE()）
                string connectionString = db.CurrentConnectionConfig.ConnectionString;
                string dbName = GetDatabaseNameFromConnectionString(connectionString);

                if (string.IsNullOrEmpty(dbName))
                {
                    throw new Exception("无法从连接字符串中获取数据库名，请检查连接字符串是否包含 database=xxx");
                }

                // 用提取的数据库名替代 DATABASE()，确保查询当前库的表
                var tables = db.Ado.SqlQuery<string>($@"
                            SELECT table_name 
                            FROM information_schema.tables 
                            WHERE table_schema = '{dbName}'  -- 显式指定数据库名
                              AND table_type = 'BASE TABLE'");
                return tables;
            }
            // 其他数据库类型（如 SQL Server）可在此扩展
            else if (db.CurrentConnectionConfig.DbType == SqlSugar.DbType.SqlServer)
            {
                // SQL Server 查询表名
                return db.Ado.SqlQuery<string>(@"
                    SELECT TABLE_NAME 
                    FROM INFORMATION_SCHEMA.TABLES 
                    WHERE TABLE_TYPE = 'BASE TABLE'");
                    }
            else
            {
                throw new NotSupportedException($"暂不支持该数据库类型的表名查询：{db.CurrentConnectionConfig.DbType}");
            }
        }


        // 辅助方法：从 MySQL 连接字符串中提取数据库名
        // 辅助方法：从 MySQL 连接字符串中提取数据库名（兼容C#7.3）
        private string GetDatabaseNameFromConnectionString(string connectionString)
        {
            // 连接字符串格式通常为：server=xxx;database=xxx;uid=xxx;pwd=xxx;
            // 修正：先指定分割次数，再指定StringSplitOptions（适配C#7.3）
            var parts = connectionString.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var part in parts)
            {
                // 修正：先指定分割次数，再指定StringSplitOptions
                var keyValue = part.Split(new[] { '=' }, 2, StringSplitOptions.None); // 按第一个等号分割

                if (keyValue.Length == 2 && keyValue[0].Trim().Equals("database", StringComparison.OrdinalIgnoreCase))
                {
                    return keyValue[1].Trim(); // 返回 database= 后面的值
                }
            }
            return null;
        }

    }

}
